home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / zoom.c < prev   
C/C++ Source or Header  |  1994-08-01  |  11KB  |  484 lines

  1. /*
  2.  * $Id: zoom.c,v 0.91 1994/02/20 00:53:21 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  *  Purpose:
  26.  *     Magnify a region of the image to the window/screen size.
  27.  *
  28.  *   Limitations:
  29.  *     Only integer zoom factors supported. Could be easily lifted
  30.  *     if there is any request.
  31.  *
  32.  */
  33. #if !defined(lint) && defined(F_ID)
  34. char *id_zoom = "$Id: zoom.c,v 0.91 1994/02/20 00:53:21 zhao Pre-Release $";
  35. #endif
  36.  
  37. #include "bit.h"
  38. #include "extern.h"
  39. #include <math.h>
  40.  
  41. /******************** Limits ******************************/
  42.  
  43. #define DEF_ZOOM   3.0        /* default zoom factors */
  44. #define MIN_ZOOM   2.0        /* minimum factor       */
  45. #define MAX_ZOOM  10.0        /* maximum factor       */
  46.  
  47. /********************* local variables *********************/
  48.  
  49. static int zx, zy, dx, dy;    /* zoom region          */
  50. static int fr_col = 1;        /* frame color          */
  51. static float zoomx, zoomy, z0;    /* zoom factors         */
  52. static float maxzx, maxzy;    /* maximum zoom factors */
  53. static int zsmooth;        /* smooth zooming. Undocumented */
  54.  
  55. /********************** local functions **********************/
  56.  
  57. static int zoom_init(IPTR, int);/* initialize          */
  58. static int zoom_popup(IPTR);    /* handle pop-up       */
  59. static int zoom_kbd(IPTR, int);    /* handle keyboard     */
  60. static void zoom_mouse(IPTR, long);    /* mouse event handler */
  61. static int zooming(IPTR);    /* yep, do it          */
  62.  
  63.  
  64. /****************************************************************
  65.  * Global entry point
  66.  ****************************************************************/
  67. int
  68. image_zoom(IPTR im)
  69. {
  70.     int done = 0;
  71.     short val = 0;
  72.     long dev;
  73.  
  74.     if (!image_ready(im, "Zoom"))
  75.     return -1;
  76.  
  77.     deactivate_all_forms();
  78.     zoom_init(im, 0);
  79.  
  80.     /* what to do if window resizes */
  81.     install_wm_handler(zoom_init);
  82.  
  83.     /* force rectangluar region */
  84.     set_rubber_obj(RB_RECT);
  85.  
  86.     /* looping until ESC or popup entry done is selected */
  87.     do
  88.       {
  89.       dev = rubber_cursor(win_id, &val, &zx, &zy, dx, dy, fr_col);
  90.  
  91.       switch (bit_handle_event(dev, val))
  92.         {
  93.         case MENUBUTTON:
  94.         done = val && zoom_popup(im);
  95.         break;
  96.         case KEYBD:
  97.         done = zoom_kbd(im, val);
  98.         break;
  99.         case ESCKEY:
  100.         done = (val > 0);
  101.         break;
  102.         case LEFTMOUSE:
  103.         case MIDDLEMOUSE:
  104.         if (val)
  105.             zoom_mouse(im, dev);
  106.         break;
  107.         }
  108.       }
  109.     while (!done);
  110.  
  111.     /* clean up */
  112.     rubber_finish();
  113.     rectzoom(1.0, 1.0);
  114.     fl_activate_all_forms();
  115.     remove_wm_handler(zoom_init);
  116.     return 0;
  117. }
  118.  
  119.  
  120. /**********************************************************
  121.  * Show current zoom factos in InfoPanel
  122.  *********************************************************/
  123. static void
  124. show_zoom_factor(void)
  125. {
  126.     char rep[30];
  127.     sprintf(rep, "Zx=%.0f Zy=%.0f", zoomx, zoomy);
  128.     show_misc_info(rep);
  129. }
  130.  
  131. /***********************************************************
  132.  * Make sure the setup is valid:
  133.  * In single buffer mode, zoom region may not be outside image
  134.  ************************************************************/
  135. static void
  136. check_and_adjust(IPTR im)
  137. {
  138.  
  139.     /* zoom must be within min & max */
  140.     if (zoomx < MIN_ZOOM)
  141.     zoomx = MIN_ZOOM;
  142.     else if (zoomx > maxzx)
  143.     zoomx = maxzx;
  144.  
  145.     if (zoomy < MIN_ZOOM)
  146.     zoomy = MIN_ZOOM;
  147.     else if (zoomy > maxzy)
  148.     zoomy = maxzy;
  149.  
  150.     dx = (win_w - 1) / zoomx;
  151.     dy = (win_h - 1) / zoomy;
  152.  
  153.     if (!double_buf)
  154.       {
  155.       if (dx >= im->w)
  156.           dx = im->w - 1;
  157.       if (dy >= im->h)
  158.           dy = im->h - 1;
  159.  
  160.       /* zoom region must be inside of image */
  161.       if (zx < im->xi)
  162.           zx = im->xi;
  163.       if (zy < im->yi)
  164.           zy = im->yi;
  165.  
  166.       if (zx + dx - 1 > im->xf)
  167.           zx = im->xf - dx + 1;
  168.       if (zy + dy - 1 > im->yf)
  169.           zy = im->yf - dy + 1;
  170.       }
  171.     /* show the possibly adjusted zoom factors */
  172.     show_zoom_factor();
  173. }
  174.  
  175. /******************************************************************
  176.  * Initialization
  177.  ******************************************************************/
  178. /* ARGSUSED */
  179. static int
  180. zoom_init(IPTR im, int wme)
  181. {
  182.     int rect_minx = 40, rect_miny = 40;
  183.  
  184.  
  185.     /* default zoom factor magnifies image to full screen */
  186.     zoomx = (win_w - 1) / im->w;
  187.     zoomy = (win_h - 1) / im->h;
  188.  
  189.     /* default to uniform zooming */
  190.     zoomx = zoomy = Min(zoomx, zoomy);
  191.  
  192.     if (zoomx < DEF_ZOOM)
  193.     zoomx = zoomy = DEF_ZOOM;
  194.  
  195.  
  196.     /* zoom factors that can safely be used */
  197.     z0 = zoomx;
  198.  
  199.     /* adjust the minimum region for small images */
  200.     if (rect_minx > im->w / 2)
  201.     rect_minx = im->w / 2;
  202.  
  203.     if (rect_miny > im->h / 2)
  204.     rect_miny = im->h / 2;
  205.  
  206.     /* maximum zoom factors that can be used */
  207.     maxzx = ((float) win_w - 5.0) / rect_minx + 0.1;
  208.     maxzy = ((float) win_h - 5.0) / rect_miny + 0.1;
  209.  
  210.     /* truncate to integer */
  211.     maxzx = (float) ((int) maxzx);
  212.     maxzy = (float) ((int) maxzy);
  213.  
  214.     if (maxzx > MAX_ZOOM)
  215.     maxzx = MAX_ZOOM;
  216.  
  217.     if (maxzy > MAX_ZOOM)
  218.     maxzy = MAX_ZOOM;
  219.  
  220.     check_and_adjust(im);
  221.  
  222.     /*
  223.      * there is no point in restricting zoom region in double buffer mode as
  224.      * we simply do a rectcopy
  225.      */
  226.  
  227.     set_rubber_bounds(!double_buf, im->xi, im->yi, im->w, im->h);
  228.  
  229.     set_rubber_center(1);
  230.     return 0;
  231. }
  232.  
  233.  
  234. /***************************************************************
  235.  * Handle zooming by leftmouse or middlemouse
  236.  ************************************************************/
  237.  
  238. static void
  239. zoom_mouse(IPTR im, long dev)
  240. {
  241.     if (control_down)
  242.       {
  243.       if (dev == LEFTMOUSE)
  244.         {
  245.         zoomx += 1.0;
  246.         zoomy += 1.0;
  247.         }
  248.       else
  249.         {
  250.         zoomx -= 1.0;
  251.         zoomy -= 1.0;
  252.         }
  253.       check_and_adjust(im);
  254.       }
  255.     else
  256.     zooming(im);
  257. }
  258.  
  259. /*******************************************************************
  260.  * Handle zoom popup menu
  261.  * return 1 if finsihing else zero
  262.  *****************************************************************/
  263. static int
  264. zoom_popup(IPTR im)
  265. {
  266.     int ret, c;
  267.     static long zoom_menu = -1;
  268.  
  269.     if (zoom_menu < 0)
  270.     zoom_menu = defpup("Zoom%t|Help|BColor|2x2|3x3|4x4|5x5|"
  271.                "Return %x100");
  272.  
  273.  
  274.     ret = 0;
  275.     switch ((c = dopup(zoom_menu)))
  276.       {
  277.       case 1:
  278.       help_cb(0, HELP_ZOOM);
  279.       break;
  280.       case 2:
  281.       ++fr_col;
  282.       fr_col %= over_pup_colors;
  283.       rubber_show(fr_col);
  284.       break;
  285.       case 3:
  286.       case 4:
  287.       case 5:
  288.       case 6:
  289.       zoomx = zoomy = (c - 1);
  290.       break;
  291.       case 7:
  292.       zsmooth = !zsmooth;
  293.       break;
  294.       case 100:
  295.       ret = 1;
  296.       break;
  297.       }
  298.     check_and_adjust(im);
  299.     return ret;
  300. }
  301.  
  302. /*******************************************************************
  303.  * Handle all keyboard events. Return 1 if ESC else 0
  304.  ******************************************************************/
  305. static int
  306. zoom_kbd(IPTR im, int val)
  307. {
  308.     int ret = 0;
  309.  
  310.     switch (val)
  311.       {
  312.       case 'x':
  313.       zoomx += 1.0;
  314.       break;
  315.       case 'X':
  316.       zoomx -= 1.0;
  317.       break;
  318.       case 'y':
  319.       zoomy += 1.0;
  320.       break;
  321.       case 'Y':
  322.       zoomy -= 1.0;
  323.       break;
  324.       case '0':
  325.       zoomx = zoomy = z0;
  326.       break;
  327.       case 27:
  328.       ret = 1;
  329.       break;
  330.       default:
  331.       break;
  332.       }
  333.     check_and_adjust(im);
  334.     return ret;
  335. }
  336.  
  337. static int newx, newy;
  338. static int xd, yd;
  339.  
  340. /****************************************************************
  341.  * Magnify the requested region (zx, zy, dx, dy) in double buffer
  342.  * mode.
  343.  ****************************************************************/
  344. /* ARGSUSED */
  345. static int
  346. dbl_zoom_it(IPTR im)
  347. {
  348.     rectcopy(zx, zy, zx + dx - 1, zy + dy - 1, xd, yd);
  349.     return 0;
  350. }
  351.  
  352. /********************************************************************
  353.  * Magnify in single buffer mode: We get a piece of image from the
  354.  * image matrix and use hardwar zoom to show it
  355.  *******************************************************************/
  356.  
  357. static int
  358. sgl_zoom_it(IPTR im)
  359. {
  360.     void **aa;
  361.  
  362.     set_current_window(win_id);
  363.     reshapeviewport();
  364.  
  365.     if (!zsmooth)        /* pixel replication   */
  366.       {
  367.       rectzoom(zoomx, zoomy);
  368.       if ((aa = get_subimage(im, zx, zy, dx, dy)))
  369.         {
  370.         Rectwrite(xd, yd, xd + dx - 1, yd + dy - 1, aa[0]);
  371.         free_mat(aa);
  372.         }
  373.       }
  374.     else
  375.       {
  376.       /* linear interpolation. Undocumented  */
  377.       IPTR zim = get_mem_imgptr();
  378.  
  379.       memcpy(zim, im, sizeof(*im));
  380.       zim->ok = 0;
  381.       zim->mraster = zim->raster = 0;
  382.  
  383.       rectzoom(1.0, 1.0);
  384.       aa = get_subimage(im, zx, zy, dx, dy);
  385.       if (fill_image_struct(zim, aa, dy, dx, im->type) < 0)
  386.           return -1;
  387.  
  388.       /*
  389.        * scale it. The third parameter is the subpixel sampling
  390.        * parameter: 1--simple blening, 2-- box filter
  391.        */
  392.  
  393.       img_scale(zim, newy, newx, 1, 0, 0);
  394.       display_image(zim, 0, 0);
  395.       free_image(zim);
  396.       }
  397.     return 0;
  398. }
  399.  
  400. /**********************************************************************
  401.  * Continuously zooming as long as mouse button is down
  402.  *********************************************************************/
  403. static int
  404. zooming(IPTR im)
  405. {
  406.     int ozx = 0, ozy = 0;
  407.     int oreport = report_level;    /* save old settings */
  408.     int (*zoom_it) (IPTR);
  409.  
  410.     rubber_hide();
  411.  
  412.     zoom_it = (double_buf ? dbl_zoom_it : sgl_zoom_it);
  413.  
  414.     /* shut up reporting */
  415.     report_level = -1;
  416.  
  417.     /* zoomed size */
  418.     newx = dx * zoomx;
  419.     newy = dy * zoomy;
  420.  
  421.     /* lower left corner in window */
  422.     xd = (win_w - newx) / 2;
  423.     yd = (win_h - newy) / 2;
  424.  
  425.     if (!double_buf)
  426.       {
  427.  
  428.       /* we can get away with rectcopy for first time only */
  429.       if (!zsmooth)
  430.         {
  431.         set_current_window(win_id);
  432.         reshapeviewport();
  433.         rectzoom(zoomx, zoomy);
  434.         rectcopy(zx, zy, dx + zx - 1, dy + zy - 1, xd, yd);
  435.         }
  436.       else
  437.         {
  438.         zoom_it(im);
  439.         }
  440.  
  441.  
  442.       WHERE_R2W(zx, zy, win_xo, win_yo);
  443.       ozx = zx - dx / 2;
  444.       ozy = zy - dy / 2;
  445.       }
  446.     else
  447.       {
  448.       rectzoom(zoomx, zoomy);
  449.       frontbuffer(1);
  450.       backbuffer(0);
  451.       }
  452.  
  453.     /* zooming while mouse is down */
  454.     do
  455.       {
  456.       WHERE_R2W(zx, zy, win_xo, win_yo);
  457.       zx -= dx / 2;
  458.       zy -= dy / 2;
  459.       if (zx != ozx || zy != ozy)
  460.         {
  461.         ozx = zx;
  462.         ozy = zy;
  463.         check_and_adjust(im);
  464.         show_rect_ori(zx, zy);
  465.         zoom_it(im);
  466.         }
  467.       }
  468.     while (mouse_down);
  469.  
  470. #ifndef SGL_BUF
  471.     if (double_buf)
  472.       {
  473.       frontbuffer(0);
  474.       backbuffer(1);
  475.       }
  476. #endif
  477.     /* clean up */
  478.     rectzoom(1.0, 1.0);
  479.     im->io->display(im, 0, 1);
  480.     rubber_moveto(&zx, &zy, &dx, &dy);
  481.     report_level = oreport;
  482.     return 0;
  483. }
  484.